package repository

import (
	"ai-curd/oo"
	"ai-curd/repository/ent"
	"ai-curd/repository/ent/user"
	"context"
)

func (repo *User) Fetch(ctx context.Context, id int) oo.User {
	return repo.FetchOne(ctx, func(query *ent.UserQuery) {
		query.Where(user.ID(id))
	})
}

func (repo *User) FetchOne(ctx context.Context, optionFunc func(query *ent.UserQuery)) oo.User {
	return repo.fetchOne(ctx, repo.db, optionFunc).Mapper()
}

func (repo *User) fetchOne(ctx context.Context, db *ent.Client, optionFunc func(query *ent.UserQuery)) *ent.User {
	builder := db.User.Query()
	optionFunc(builder)
	return builder.FirstX(ctx)
}

func (repo *User) FetchMany(ctx context.Context, optionFunc func(query *ent.UserQuery)) oo.Users {
	return repo.fetchMany(ctx, repo.db, optionFunc).Mapper()
}

func (repo *User) fetchMany(ctx context.Context, db *ent.Client, optionFunc func(query *ent.UserQuery)) ent.Users {
	builder := db.User.Query()
	optionFunc(builder)
	return builder.AllX(ctx)
}

func (repo *User) Count(ctx context.Context, option func(query *ent.UserQuery)) int {
	return repo.count(ctx, repo.db, option)
}

func (repo *User) count(ctx context.Context, db *ent.Client, option func(query *ent.UserQuery)) int {
	builder := db.User.Query()
	option(builder)
	return builder.CountX(ctx)
}

func (repo *User) Exist(ctx context.Context, option func(query *ent.UserQuery)) bool {
	return repo.exist(ctx, repo.db, option)
}

func (repo *User) exist(ctx context.Context, db *ent.Client, option func(query *ent.UserQuery)) bool {
	builder := db.User.Query()
	option(builder)
	return builder.ExistX(ctx)
}

func (repo *User) Create(ctx context.Context, option func(query *ent.UserCreate)) oo.User {
	return repo.create(ctx, repo.db, option).Mapper()
}

func (repo *User) create(ctx context.Context, db *ent.Client, option func(query *ent.UserCreate)) *ent.User {
	builder := db.User.Create()
	option(builder)
	return builder.SaveX(ctx)
}

func (repo *User) Update(ctx context.Context, option func(query *ent.UserUpdate)) int {
	return repo.update(ctx, repo.db, option)
}

func (repo *User) update(ctx context.Context, db *ent.Client, option func(query *ent.UserUpdate)) int {
	builder := db.User.Update()
	option(builder)
	return builder.SaveX(ctx)
}

func (repo *User) Delete(ctx context.Context, option func(query *ent.UserDelete)) int {
	return repo.delete(ctx, repo.db, option)
}

func (repo *User) delete(ctx context.Context, db *ent.Client, option func(query *ent.UserDelete)) int {
	builder := db.User.Delete()
	option(builder)
	return builder.ExecX(ctx)
}

func (repo *User) Save(ctx context.Context, ooUser oo.User) oo.User {
	return repo.save(ctx, repo.db, ooUser).Mapper()
}

func (repo *User) save(ctx context.Context, db *ent.Client, ooUser oo.User) *ent.User {
	builder := db.User.Create()
	ooUser.CategoryIsPresent(func(v int) { builder.SetCategory(v) })
	ooUser.LevelIsPresent(func(v int) { builder.SetLevel(v) })
	ooUser.PhoneIsPresent(func(v string) { builder.SetPhone(v) })
	ooUser.NicknameIsPresent(func(v string) { builder.SetNickname(v) })
	return builder.SaveX(ctx)
}

func (repo *User) Modify(ctx context.Context, ooUser oo.User) int {
	return repo.modify(ctx, repo.db, ooUser)
}

func (repo *User) modify(ctx context.Context, db *ent.Client, ooUser oo.User) int {
	builder := db.User.Update()
	ooUser.CategoryIsPresent(func(v int) { builder.SetCategory(v) })
	ooUser.LevelIsPresent(func(v int) { builder.SetLevel(v) })
	ooUser.PhoneIsPresent(func(v string) { builder.SetPhone(v) })
	ooUser.NicknameIsPresent(func(v string) { builder.SetNickname(v) })
	return builder.Where(user.ID(ooUser.ID())).SaveX(ctx)
}